﻿// Gateway.Api 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
// 
// 本项目主要遵循 MIT 许可证和 Apache 许可证（版本 2.0）进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
// 
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动！任何基于本项目二次开发而产生的一切法律纠纷和责任，我们不承担任何责任！

using Aurora.AI.Common.Models;
using Aurora.AI.Wiki;
using Aurora.AI.Wiki.Domain.Domain.Wikis.Aggregates;
using Aurora.AI.Wiki.Services;
using Aurora.AI.Wiki.Services.Wiki;
using Aurora.TaskScheduler.Extension;
using FileServer.Abstractions;
using Gateway.Infrastructure.Provider.Operator;
using Gateway.IQuery;
using Gateway.UI.Api.TaskJobs;

namespace Gateway.UI.Api.Controllers.Ai.Wiki;

/// <summary>
/// ai wiki 服务
/// </summary>
[ApiController]
[Route("api/ai/wiki/wiki")]
public class AiWikiController(
    WikiService wikiService,
    IOperatorProvider operatorProvider,
    WikiDetailService wikiDetailService,
    TaskJobUtil taskJobUtil,
    IFileStorage fileStorage,
    IServiceProvider serviceProvider) : BaseController
{
    /// <summary>
    /// 添加
    /// </summary>
    /// <param name="request"></param>
    /// <returns></returns>
    [HttpPost("add")]
    public async Task<bool> Add(Aurora.AI.Wiki.Domain.Domain.Wikis.Aggregates.Wiki request)
    {
        request.Creator = operatorProvider.GetOperator().OperatorId;
        return await wikiService.Create(request);
    }

    /// <summary>
    /// 编辑
    /// </summary>
    /// <param name="request"></param>
    /// <returns></returns>
    [HttpPost("update")]
    public async Task<bool> Update(Aurora.AI.Wiki.Domain.Domain.Wikis.Aggregates.Wiki request)
    {
        request.Modifier = operatorProvider.GetOperator().OperatorId;
        return await wikiService.Update(request);
    }

    /// <summary>
    /// 删除
    /// </summary>
    /// <param name="id"></param>
    /// <returns></returns>
    [HttpGet("delete")]
    public async Task<bool> Delete(string id)
    {
        Aurora.AI.Wiki.Domain.Domain.Wikis.Aggregates.Wiki wiki = await wikiService.GetByIdAsync(id);
        List<string> wikiDetailIdsByWikiId = await wikiDetailService.GetWikiDetailIdsByWikiId(id);
        await wikiService.Remove(id);
        // 还需要删除向量
        WikiMemoryService wikiMemoryService = serviceProvider.GetRequiredService<WikiMemoryService>();
        WikiSettingService wikiSettingService = serviceProvider.GetRequiredService<WikiSettingService>();
        AICommonSetting setting = await wikiSettingService.GetCommonSetting();
        foreach (var item in wikiDetailIdsByWikiId)
        {
            try
            {
                var memoryServerless =
                    wikiMemoryService.CreateMemoryServerless(wiki.EmbeddingModel, wiki.Model, setting);
                await memoryServerless.DeleteDocumentAsync(item, "wiki");
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
            }
        }

        return true;
    }

    /// <summary>
    /// 列表
    /// </summary>
    /// <param name="request"></param>
    /// <returns></returns>
    [HttpPost("page/list")]
    public async Task<PageResult<Aurora.AI.Wiki.Domain.Domain.Wikis.Aggregates.Wiki>> GetPageList(
        BasePageRequest request)
    {
        var data = await wikiService.PageList(request.Page, request.PageSize);
        return PageResult<Aurora.AI.Wiki.Domain.Domain.Wikis.Aggregates.Wiki>.Create(data.list, data.total);
    }

    /// <summary>
    /// 列表
    /// </summary>
    /// <returns></returns>
    [HttpGet("list/available")]
    public async Task<List<Aurora.AI.Wiki.Domain.Domain.Wikis.Aggregates.Wiki>> GetAvailableList()
    {
        return await wikiService.GetAvailableList();
    }

    /// <summary>
    /// 详情
    /// </summary>
    /// <param name="id"></param>
    /// <returns></returns>
    [HttpGet("detail")]
    public async Task<Aurora.AI.Wiki.Domain.Domain.Wikis.Aggregates.Wiki> Detail(string id)
    {
        return await wikiService.GetByIdAsync(id);
    }


    /// <summary>
    /// 知识库知识管理 创建知识点
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [HttpPost("knowledge/create")]
    public async Task<string> CreateKnowledge(WikiDetail input)
    {
        if (string.IsNullOrEmpty(input.WikiId))
        {
            throw new MyException("知识库标识为空，请重试或刷新页面");
        }

        if (string.IsNullOrEmpty(input.Type))
        {
            input.Type = "file";
        }

        input.Creator = operatorProvider.GetOperator().OperatorId;
        var data = await wikiDetailService.Add(input);
        // 开始 后台执行任务
        taskJobUtil.InvokeLater(typeof(WikiDetailJob), data);
        return data.Id;
    }


    /// <summary>
    /// 获取知识列表-分页
    /// </summary>
    /// <param name="request"></param>
    /// <returns></returns>
    [HttpPost("knowledge/page/list")]
    public async Task<PageResult<WikiDetailPageListResponse>> GetKnowledgeList(WikiDetailPageRequest request)
    {
        var data = await wikiDetailService.GetPageListAsync(request);
        return PageResult<WikiDetailPageListResponse>.Create(data.list, data.total);
    }

    /// <summary>
    /// 查看 知识列表下的 向量
    /// </summary>
    /// <param name="wikiDetailId"></param>
    /// <param name="page"></param>
    /// <param name="size"></param>
    /// <returns></returns>
    [HttpGet("knowledge/vector/page/list")]
    public async Task<PageResult<WikiDetailVectorQuantityResponse>> GetWikiDetailVectorQuantityAsync(
        string wikiDetailId, int page, int size)
    {
        var data = await wikiDetailService.GetWikiDetailVectorQuantityAsync(wikiDetailId, page, size);
        return PageResult<WikiDetailVectorQuantityResponse>.Create(data.list, data.total);
    }


    /// <summary>
    /// 向量搜索查询
    /// </summary>
    /// <param name="request"></param>
    /// <returns></returns>
    [HttpPost("knowledge/vector/search")]
    public async Task<SearchVectorQuantityResult> SearchVectorQuantityAsync(SearchVectorQuantityRequest request)
    {
        if (string.IsNullOrEmpty(request.WikiId))
        {
            throw new MyException("知识库标识为空，请重试或刷新页面");
        }

        var data = await wikiDetailService.SearchVectorQuantityAsync(request.WikiId, request.MinRelevance,
            request.Search);
        // 根据文件id 查询文件信息
        if (data.Result.Count <= 0)
        {
            return data;
        }

        // 文件标识集合 去到外层查询文件的名称
        var fileIds = data.Result.Where(x => !string.IsNullOrEmpty(x.FileId)).Select(x => x.FileId).ToList();
        if (fileIds.Count <= 0)
            return data;
        var fileInfos = await fileStorage.GetByIds(fileIds);
        foreach (SearchVectorQuantityResponse item in data.Result)
        {
            if (string.IsNullOrEmpty(item.FileId))
            {
                continue;
            }

            var first = fileInfos.FirstOrDefault(x => x.Id.Equals(item.FileId));
            if (first != null)
            {
                item.FileName = first.OriginName;
                item.FullPath = first.Path;
            }
        }

        return data;
    }

    /// <summary>
    /// 删除知识点
    /// </summary>
    /// <param name="id"></param>
    /// <returns></returns>
    [HttpGet("knowledge/remove")]
    public async Task<bool> RemoveDetailAsync(string id)
    {
        await wikiDetailService.RemoveWikiDetailAsync(id);
        return true;
    }

    /// <summary>
    /// 知识点向量重试
    /// </summary>
    /// <param name="id"></param>
    /// <returns></returns>
    [HttpGet("knowledge/vector/retry")]
    public async Task<bool> RetryVectorDetailAsync(string id)
    {
        var data = await wikiDetailService.GetByIdAsync(id);
        if (data == null)
        {
            throw new MyException("未找到数据");
        }

        // 开始 后台执行任务
        taskJobUtil.InvokeLater(typeof(WikiDetailJob), data);
        return true;
    }


    /// <summary>
    /// 删除向量
    /// </summary>
    /// <param name="documentId"></param>
    /// <param name="wikiDetailId"></param>
    /// <returns></returns>
    [HttpGet("knowledge/vector/remove")]
    public async Task<bool> RemoveDetailVectorQuantityAsync(string documentId, string wikiDetailId)
    {
        await wikiDetailService.RemoveWikiDetailVectorQuantityAsync(documentId, wikiDetailId);
        return true;
    }
}